home *** CD-ROM | disk | FTP | other *** search
/ GameStar 2004 April / Gamestar_61_2004-04_dvdb.iso / DVDStar / Editace / hltp.exe / {app} / Source Code / Zoners Half-Life Tools / hlcsg / map.cpp < prev    next >
C/C++ Source or Header  |  2002-11-28  |  21KB  |  626 lines

  1. #include "csg.h"
  2.  
  3. int             g_nummapbrushes;
  4. brush_t         g_mapbrushes[MAX_MAP_BRUSHES];
  5.  
  6. int             g_numbrushsides;
  7. side_t          g_brushsides[MAX_MAP_SIDES];
  8.  
  9. int             g_nMapFileVersion;
  10.  
  11. static const vec3_t   s_baseaxis[18] = {
  12.     {0, 0, 1}, {1, 0, 0}, {0, -1, 0},                      // floor
  13.     {0, 0, -1}, {1, 0, 0}, {0, -1, 0},                     // ceiling
  14.     {1, 0, 0}, {0, 1, 0}, {0, 0, -1},                      // west wall
  15.     {-1, 0, 0}, {0, 1, 0}, {0, 0, -1},                     // east wall
  16.     {0, 1, 0}, {1, 0, 0}, {0, 0, -1},                      // south wall
  17.     {0, -1, 0}, {1, 0, 0}, {0, 0, -1},                     // north wall
  18. };
  19.  
  20. // =====================================================================================
  21. //  TextureAxisFromPlane
  22. // =====================================================================================
  23. void            TextureAxisFromPlane(const plane_t* const pln, vec3_t xv, vec3_t yv)
  24. {
  25.     int             bestaxis;
  26.     vec_t           dot, best;
  27.     int             i;
  28.  
  29.     best = 0;
  30.     bestaxis = 0;
  31.  
  32.     for (i = 0; i < 6; i++)
  33.     {
  34.         dot = DotProduct(pln->normal, s_baseaxis[i * 3]);
  35.         if (dot > best)
  36.         {
  37.             best = dot;
  38.             bestaxis = i;
  39.         }
  40.     }
  41.  
  42.     VectorCopy(s_baseaxis[bestaxis * 3 + 1], xv);
  43.     VectorCopy(s_baseaxis[bestaxis * 3 + 2], yv);
  44. }
  45.  
  46. #define ScaleCorrection    (1.0/128.0)
  47.  
  48. // =====================================================================================
  49. //  CopySKYtoCLIP
  50. //      clips a particluar sky brush
  51. // =====================================================================================
  52. static void     CopySKYtoCLIP(const brush_t* const b)
  53. {
  54.     int             i;
  55.     entity_t*       mapent;
  56.     brush_t*        newbrush;
  57.  
  58.     if (b->contents != CONTENTS_SKY)
  59.         Error("[MOD] CopySKYtoCLIP: Got a NON-SKY for passed brush! (%s)",b->contents ); 
  60.  
  61.     hlassert(b->contents == CONTENTS_SKY);                 // Only SKY brushes should be passed down to this function(sanity check)
  62.     hlassert(b->entitynum == 0);                           // SKY must be in worldspawn entity
  63.  
  64.     mapent = &g_entities[b->entitynum];
  65.     mapent->numbrushes++;
  66.  
  67.     newbrush = &g_mapbrushes[g_nummapbrushes];
  68.     newbrush->entitynum = b->entitynum;
  69.     newbrush->brushnum = g_nummapbrushes - mapent->firstbrush;
  70.     newbrush->firstside = g_numbrushsides;
  71.     newbrush->numsides = b->numsides;
  72.     newbrush->contents = CONTENTS_CLIP;
  73.     newbrush->noclip = 0;
  74.  
  75.     for (i = 0; i < b->numsides; i++)
  76.     {
  77.         int             j;
  78.  
  79.         side_t*         side = &g_brushsides[g_numbrushsides];
  80.  
  81.         *side = g_brushsides[b->firstside + i];
  82.         safe_strncpy(side->td.name, "CLIP", sizeof(side->td.name));
  83.  
  84.         for (j = 0; j < NUM_HULLS; j++)
  85.         {
  86.             newbrush->hulls[j].faces = NULL;
  87.             newbrush->hulls[j].bounds = b->hulls[j].bounds;
  88.         }
  89.  
  90.         g_numbrushsides++;
  91.         hlassume(g_numbrushsides < MAX_MAP_SIDES, assume_MAX_MAP_SIDES);
  92.     }
  93.  
  94.     g_nummapbrushes++;
  95.     hlassume(g_nummapbrushes < MAX_MAP_BRUSHES, assume_MAX_MAP_BRUSHES);
  96. }
  97.  
  98. // =====================================================================================
  99. //  HandleSKYCLIP
  100. //      clips the whole sky, unconditional of g_skyclip
  101. // =====================================================================================
  102. static void     HandleSKYCLIP()
  103. {
  104.     int             i;
  105.     int             last;
  106.     entity_t*       e = &g_entities[0];
  107.  
  108.     for (i = e->firstbrush, last = e->firstbrush + e->numbrushes; i < last; i++)
  109.     {
  110.         if (g_mapbrushes[i].contents == CONTENTS_SKY)
  111.         {
  112.             CopySKYtoCLIP(&g_mapbrushes[i]);
  113.         }
  114.     }
  115. }
  116.  
  117. // =====================================================================================
  118. //  ParseBrush
  119. //      parse a brush from script
  120. // =====================================================================================
  121. static contents_t ParseBrush(entity_t* mapent)
  122. {
  123.     brush_t*        b;
  124.     int             i, j;
  125.     side_t*         side;
  126.     contents_t      contents;
  127.     bool            ok;
  128.  
  129.     hlassume(g_nummapbrushes < MAX_MAP_BRUSHES, assume_MAX_MAP_BRUSHES);
  130.  
  131.     b = &g_mapbrushes[g_nummapbrushes];
  132.     g_nummapbrushes++;
  133.     b->firstside = g_numbrushsides;
  134.     b->entitynum = g_numentities - 1;
  135.     b->brushnum = g_nummapbrushes - mapent->firstbrush - 1;
  136.  
  137. #ifdef HLCSG_CLIPECONOMY // AJM
  138.     b->noclip = 0;
  139. #endif
  140.  
  141.     mapent->numbrushes++;
  142.  
  143.  
  144.     ok = GetToken(true);
  145.     while (ok)
  146.     {
  147.         g_TXcommand = 0;
  148.         if (!strcmp(g_token, "}"))
  149.         {
  150.             break;
  151.         }
  152.  
  153.         hlassume(g_numbrushsides < MAX_MAP_SIDES, assume_MAX_MAP_SIDES);
  154.         side = &g_brushsides[g_numbrushsides];
  155.         g_numbrushsides++;
  156.  
  157.         b->numsides++;
  158.  
  159.         // read the three point plane definition
  160.         for (i = 0; i < 3; i++)
  161.         {
  162.             if (i != 0)
  163.             {
  164.                 GetToken(true);
  165.             }
  166.             if (strcmp(g_token, "("))
  167.             {
  168.                 Error("Parsing Entity %i, Brush %i, Side %i : Expecting '(' got '%s'",
  169.                       b->entitynum, b->brushnum, b->numsides, g_token);
  170.             }
  171.  
  172.             for (j = 0; j < 3; j++)
  173.             {
  174.                 GetToken(false);
  175.                 side->planepts[i][j] = atof(g_token);
  176.             }
  177.  
  178.             GetToken(false);
  179.             if (strcmp(g_token, ")"))
  180.             {
  181.                 Error("Parsing    Entity %i, Brush %i, Side %i : Expecting ')' got '%s'",
  182.                       b->entitynum, b->brushnum, b->numsides, g_token);
  183.             }
  184.         }
  185.  
  186.         // read the     texturedef
  187.         GetToken(false);
  188.         strupr(g_token);
  189.         safe_strncpy(side->td.name, g_token, sizeof(side->td.name));
  190.  
  191.         if (g_nMapFileVersion < 220)                       // Worldcraft 2.1-, Radiant
  192.         {
  193.             GetToken(false);
  194.             side->td.vects.valve.shift[0] = atof(g_token);
  195.             GetToken(false);
  196.             side->td.vects.valve.shift[1] = atof(g_token);
  197.             GetToken(false);
  198.             side->td.vects.valve.rotate = atof(g_token);
  199.             GetToken(false);
  200.             side->td.vects.valve.scale[0] = atof(g_token);
  201.             GetToken(false);
  202.             side->td.vects.valve.scale[1] = atof(g_token);
  203.         }
  204.         else                                               // Worldcraft 2.2+
  205.         {
  206.             // texture U axis
  207.             GetToken(false);
  208.             if (strcmp(g_token, "["))
  209.             {
  210.                 hlassume(false, assume_MISSING_BRACKET_IN_TEXTUREDEF);
  211.             }
  212.  
  213.             GetToken(false);
  214.             side->td.vects.valve.UAxis[0] = atof(g_token);
  215.             GetToken(false);
  216.             side->td.vects.valve.UAxis[1] = atof(g_token);
  217.             GetToken(false);
  218.             side->td.vects.valve.UAxis[2] = atof(g_token);
  219.             GetToken(false);
  220.             side->td.vects.valve.shift[0] = atof(g_token);
  221.  
  222.             GetToken(false);
  223.             if (strcmp(g_token, "]"))
  224.             {
  225.                 Error("missing ']' in texturedef (U)");
  226.             }
  227.  
  228.             // texture V axis
  229.             GetToken(false);
  230.             if (strcmp(g_token, "["))
  231.             {
  232.                 Error("missing '[' in texturedef (V)");
  233.             }
  234.  
  235.             GetToken(false);
  236.             side->td.vects.valve.VAxis[0] = atof(g_token);
  237.             GetToken(false);
  238.             side->td.vects.valve.VAxis[1] = atof(g_token);
  239.             GetToken(false);
  240.             side->td.vects.valve.VAxis[2] = atof(g_token);
  241.             GetToken(false);
  242.             side->td.vects.valve.shift[1] = atof(g_token);
  243.  
  244.             GetToken(false);
  245.             if (strcmp(g_token, "]"))
  246.             {
  247.                 Error("missing ']' in texturedef (V)");
  248.             }
  249.  
  250.             // Texture rotation is implicit in U/V axes.
  251.             GetToken(false);
  252.             side->td.vects.valve.rotate = 0;
  253.  
  254.             // texure scale
  255.             GetToken(false);
  256.             side->td.vects.valve.scale[0] = atof(g_token);
  257.             GetToken(false);
  258.             side->td.vects.valve.scale[1] = atof(g_token);
  259.         }
  260.  
  261.         ok = GetToken(true);                               // Done with line, this reads the first item from the next line
  262.  
  263.         if ((g_TXcommand == '1' || g_TXcommand == '2'))
  264.         {
  265.             // We are QuArK mode and need to translate some numbers to align textures its way
  266.             // from QuArK, the texture vectors are given directly from the three points
  267.             vec3_t          TexPt[2];
  268.             int             k;
  269.             float           dot22, dot23, dot33, mdet, aa, bb, dd;
  270.  
  271.             k = g_TXcommand - '0';
  272.             for (j = 0; j < 3; j++)
  273.             {
  274.                 TexPt[1][j] = (side->planepts[k][j] - side->planepts[0][j]) * ScaleCorrection;
  275.             }
  276.             k = 3 - k;
  277.             for (j = 0; j < 3; j++)
  278.             {
  279.                 TexPt[0][j] = (side->planepts[k][j] - side->planepts[0][j]) * ScaleCorrection;
  280.             }
  281.  
  282.             dot22 = DotProduct(TexPt[0], TexPt[0]);
  283.             dot23 = DotProduct(TexPt[0], TexPt[1]);
  284.             dot33 = DotProduct(TexPt[1], TexPt[1]);
  285.             mdet = dot22 * dot33 - dot23 * dot23;
  286.             if (mdet < 1E-6 && mdet > -1E-6)
  287.             {
  288.                 aa = bb = dd = 0;
  289.                 Warning
  290.                     ("Degenerate QuArK-style brush texture : Entity %i, Brush %i @ (%f,%f,%f) (%f,%f,%f)    (%f,%f,%f)",
  291.                      b->entitynum, b->brushnum, side->planepts[0][0], side->planepts[0][1], side->planepts[0][2],
  292.                      side->planepts[1][0], side->planepts[1][1], side->planepts[1][2], side->planepts[2][0],
  293.                      side->planepts[2][1], side->planepts[2][2]);
  294.             }
  295.             else
  296.             {
  297.                 mdet = 1.0 / mdet;
  298.                 aa = dot33 * mdet;
  299.                 bb = -dot23 * mdet;
  300.                 //cc = -dot23*mdet;             // cc = bb
  301.                 dd = dot22 * mdet;
  302.             }
  303.  
  304.             for (j = 0; j < 3; j++)
  305.             {
  306.                 side->td.vects.quark.vects[0][j] = aa * TexPt[0][j] + bb * TexPt[1][j];
  307.                 side->td.vects.quark.vects[1][j] = -( /*cc */ bb * TexPt[0][j] + dd * TexPt[1][j]);
  308.             }
  309.  
  310.             side->td.vects.quark.vects[0][3] = -DotProduct(side->td.vects.quark.vects[0], side->planepts[0]);
  311.             side->td.vects.quark.vects[1][3] = -DotProduct(side->td.vects.quark.vects[1], side->planepts[0]);
  312.         }
  313.  
  314.         side->td.txcommand = g_TXcommand;                  // Quark stuff, but needs setting always
  315.     };
  316.  
  317.     b->contents = contents = CheckBrushContents(b);
  318.  
  319.     //
  320.     // origin brushes are removed, but they set
  321.     // the rotation origin for the rest of the brushes
  322.     // in the entity
  323.     //
  324.  
  325.     if (contents == CONTENTS_ORIGIN)
  326.     {
  327.         char            string[MAXTOKEN];
  328.         vec3_t          origin;
  329.  
  330.         b->contents = CONTENTS_SOLID;
  331.         CreateBrush(mapent->firstbrush + b->brushnum);     // to get sizes
  332.         b->contents = contents;
  333.  
  334.         for (i = 0; i < NUM_HULLS; i++)
  335.         {
  336.             b->hulls[i].faces = NULL;
  337.         }
  338.  
  339.         if (b->entitynum != 0)  // Ignore for WORLD (code elsewhere enforces no ORIGIN in world message)
  340.         {
  341.             VectorAdd(b->hulls[0].bounds.m_Mins, b->hulls[0].bounds.m_Maxs, origin);
  342.             VectorScale(origin, 0.5, origin);
  343.     
  344.             safe_snprintf(string, MAXTOKEN, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]);
  345.             SetKeyValue(&g_entities[b->entitynum], "origin", string);
  346.         }
  347.     }
  348.  
  349.     return contents;
  350. }
  351.  
  352.  
  353. // =====================================================================================
  354. //  ParseMapEntity
  355. //      parse an entity from script
  356. // =====================================================================================
  357. bool            ParseMapEntity()
  358. {
  359.     bool            all_clip = true;
  360.     int             this_entity;
  361.     entity_t*       mapent;
  362.     epair_t*        e;
  363.  
  364.     if (!GetToken(true))
  365.     {
  366.         return false;
  367.     }
  368.  
  369.     this_entity = g_numentities;
  370.  
  371.     if (strcmp(g_token, "{"))
  372.     {
  373.         Error("Parsing Entity %i, expected '{' got '%s'", this_entity, g_token);
  374.     }
  375.  
  376.     hlassume(g_numentities < MAX_MAP_ENTITIES, assume_MAX_MAP_ENTITIES);
  377.     g_numentities++;
  378.  
  379.     mapent = &g_entities[this_entity];
  380.     mapent->firstbrush = g_nummapbrushes;
  381.     mapent->numbrushes = 0;
  382.  
  383.     while (1)
  384.     {
  385.         if (!GetToken(true))
  386.             Error("ParseEntity: EOF without closing brace");
  387.  
  388.         if (!strcmp(g_token, "}"))  // end of our context
  389.             break;
  390.  
  391.         if (!strcmp(g_token, "{"))  // must be a brush
  392.         {
  393.             contents_t contents = ParseBrush(mapent);
  394.  
  395.             if ((contents != CONTENTS_CLIP) && (contents != CONTENTS_ORIGIN))
  396.                 all_clip = false;
  397.         }
  398.         else                        // else assume an epair
  399.         {
  400.             e = ParseEpair();
  401.  
  402.             if (!strcmp(e->key, "mapversion"))
  403.             {
  404.                 g_nMapFileVersion = atoi(e->value);
  405.             }
  406.  
  407.             e->next = mapent->epairs;
  408.             mapent->epairs = e;
  409.         }
  410.     }
  411.  
  412.  
  413.     if (mapent->numbrushes && all_clip)
  414.         Fatal(assume_NO_VISIBILE_BRUSHES, "Entity %i has no visible brushes\n", this_entity);
  415.  
  416.     CheckFatal();
  417.  
  418.     
  419. #ifdef ZHLT_DETAIL // AJM
  420.     if (!strcmp(ValueForKey(mapent, "classname"), "info_detail") && g_bDetailBrushes && this_entity != 0)
  421.     {
  422.         // mark all of the brushes in this entity as contents_detail
  423.         for (int i = mapent->firstbrush; i < mapent->firstbrush + mapent->numbrushes; i++)
  424.         {
  425.             g_mapbrushes[i].contents = CONTENTS_DETAIL;
  426.         }
  427.  
  428.         // move these brushes to worldspawn
  429.         {
  430.             brush_t*        temp;
  431.             int             newbrushes;
  432.             int             worldbrushes;
  433.             int             i;
  434.  
  435.             newbrushes = mapent->numbrushes;
  436.             worldbrushes = g_entities[0].numbrushes;
  437.  
  438.             temp = (brush_t*)Alloc(newbrushes * sizeof(brush_t));
  439.             memcpy(temp, g_mapbrushes + mapent->firstbrush, newbrushes * sizeof(brush_t));
  440.  
  441.             for (i = 0; i < newbrushes; i++)
  442.             {
  443.                 temp[i].entitynum = 0;
  444.             }
  445.  
  446.             // make space to move the brushes (overlapped copy)
  447.             memmove(g_mapbrushes + worldbrushes + newbrushes,
  448.                     g_mapbrushes + worldbrushes, sizeof(brush_t) * (g_nummapbrushes - worldbrushes - newbrushes));
  449.  
  450.             // copy the new brushes down
  451.             memcpy(g_mapbrushes + worldbrushes, temp, sizeof(brush_t) * newbrushes);
  452.  
  453.             // fix up indexes
  454.             g_numentities--;
  455.             g_entities[0].numbrushes += newbrushes;
  456.             for (i = 1; i < g_numentities; i++)
  457.             {
  458.                 g_entities[i].firstbrush += newbrushes;
  459.             }
  460.             memset(mapent, 0, sizeof(*mapent));
  461.             Free(temp);
  462.         }
  463.  
  464.         // delete this entity
  465.         g_numentities--;
  466.         return true;
  467.     }
  468. #endif
  469.  
  470.  
  471. #ifdef ZHLT_INFO_COMPILE_PARAMETERS // AJM
  472.     if (!strcmp(ValueForKey(mapent, "classname"), "info_compile_parameters"))
  473.     {
  474.         GetParamsFromEnt(mapent);
  475.     }
  476. #endif
  477.  
  478.     // if its the worldspawn entity and we need to skyclip, then do it
  479.     if ((this_entity == 0) && g_skyclip)                  // first entitiy
  480.     {
  481.         HandleSKYCLIP();
  482.     }
  483.  
  484.     // if the given entity only has one brush and its an origin brush
  485.     if ((mapent->numbrushes == 1) && (g_mapbrushes[mapent->firstbrush].contents == CONTENTS_ORIGIN))
  486.     {
  487.         brushhull_t*    hull = g_mapbrushes[mapent->firstbrush].hulls;
  488.  
  489.         Error("Entity %i, contains ONLY an origin brush near (%.0f,%.0f,%.0f)\n",
  490.               this_entity, hull->bounds.m_Mins[0], hull->bounds.m_Mins[1], hull->bounds.m_Mins[2]);
  491.     }
  492.  
  493.     GetVectorForKey(mapent, "origin", mapent->origin);
  494.  
  495.     // group entities are just for editor convenience
  496.     // toss all brushes into the world entity
  497.     if (!g_onlyents && !strcmp("func_group", ValueForKey(mapent, "classname")))
  498.     {
  499.         // this is pretty gross, because the brushes are expected to be
  500.         // in linear order for each entity
  501.         brush_t*        temp;
  502.         int             newbrushes;
  503.         int             worldbrushes;
  504.         int             i;
  505.  
  506.         newbrushes = mapent->numbrushes;
  507.         worldbrushes = g_entities[0].numbrushes;
  508.  
  509.         temp = (brush_t*)Alloc(newbrushes * sizeof(brush_t));
  510.         memcpy(temp, g_mapbrushes + mapent->firstbrush, newbrushes * sizeof(brush_t));
  511.  
  512.         for (i = 0; i < newbrushes; i++)
  513.         {
  514.             temp[i].entitynum = 0;
  515.         }
  516.  
  517.         // make space to move the brushes (overlapped copy)
  518.         memmove(g_mapbrushes + worldbrushes + newbrushes,
  519.                 g_mapbrushes + worldbrushes, sizeof(brush_t) * (g_nummapbrushes - worldbrushes - newbrushes));
  520.  
  521.         // copy the new brushes down
  522.         memcpy(g_mapbrushes + worldbrushes, temp, sizeof(brush_t) * newbrushes);
  523.  
  524.         // fix up indexes
  525.         g_numentities--;
  526.         g_entities[0].numbrushes += newbrushes;
  527.         for (i = 1; i < g_numentities; i++)
  528.         {
  529.             g_entities[i].firstbrush += newbrushes;
  530.         }
  531.         memset(mapent, 0, sizeof(*mapent));
  532.         Free(temp);
  533.     }
  534.  
  535.     return true;
  536. }
  537.  
  538. // =====================================================================================
  539. //  CountEngineEntities
  540. // =====================================================================================
  541. unsigned int    CountEngineEntities()
  542. {
  543.     unsigned int x;
  544.     unsigned num_engine_entities = 0;
  545.     entity_t*       mapent = g_entities;
  546.  
  547.     // for each entity in the map
  548.     for (x=0; x<g_numentities; x++, mapent++)
  549.     {
  550.         const char* classname = ValueForKey(mapent, "classname");
  551.  
  552.         // if its a light_spot or light_env, dont include it as an engine entity!
  553.         if (classname)
  554.         {
  555.             if (   !strncasecmp(classname, "light", 5) 
  556.                 || !strncasecmp(classname, "light_spot", 10) 
  557.                 || !strncasecmp(classname, "light_environment", 17)
  558.                )
  559.             {
  560.                 const char* style = ValueForKey(mapent, "style");
  561.                 const char* targetname = ValueForKey(mapent, "targetname");
  562.  
  563.                 // lightspots and lightenviroments dont have a targetname or style
  564.                 if (!strlen(targetname) && !atoi(style))
  565.                 {
  566.                     continue;
  567.                 }
  568.             }
  569.         }
  570.  
  571.         num_engine_entities++;
  572.     }
  573.  
  574.     return num_engine_entities;
  575. }
  576.  
  577. // =====================================================================================
  578. //  LoadMapFile
  579. //      wrapper for LoadScriptFile
  580. //      parse in script entities
  581. // =====================================================================================
  582. const char*     ContentsToString(const contents_t type);
  583.  
  584. void            LoadMapFile(const char* const filename)
  585. {
  586.     unsigned num_engine_entities;
  587.  
  588.     LoadScriptFile(filename);
  589.  
  590.     g_numentities = 0;
  591.  
  592.     while (ParseMapEntity())
  593.     {
  594.     }
  595.  
  596.     // AJM debug
  597.     /*
  598.     for (int i = 0; i < g_numentities; i++)
  599.     {
  600.         Log("entity: %i - %i brushes - %s\n", i, g_entities[i].numbrushes, ValueForKey(&g_entities[i], "classname"));
  601.     }
  602.     Log("total entities: %i\ntotal brushes: %i\n\n", g_numentities, g_nummapbrushes);
  603.  
  604.     for (i = g_entities[0].firstbrush; i < g_entities[0].firstbrush + g_entities[0].numbrushes; i++)
  605.     {
  606.         Log("worldspawn brush %i: contents %s\n", i, ContentsToString((contents_t)g_mapbrushes[i].contents)); 
  607.     }
  608.     */
  609.  
  610.     num_engine_entities = CountEngineEntities();
  611.  
  612.     hlassume(num_engine_entities < MAX_ENGINE_ENTITIES, assume_MAX_ENGINE_ENTITIES);
  613.  
  614.     CheckFatal();
  615.  
  616.     Verbose("Load map:%s\n", filename);
  617.     Verbose("%5i brushes\n", g_nummapbrushes);
  618.     Verbose("%5i map entities \n", g_numentities - num_engine_entities);
  619.     Verbose("%5i engine entities\n", num_engine_entities);
  620.  
  621.     // AJM: added in 
  622. #ifdef HLCSG_AUTOWAD
  623.     GetUsedTextures();
  624. #endif
  625. }
  626.